class ArcWall {
    /**
     初始化并构建场景
     * @param {object} options - 配置对象，所有参数均可选
     */
    constructor(options = {}) {
        //DOM元素获取
        this.selectors = {
            scene: options.scene || '.scene',
            world: options.world || '.world',
            wall: options.wall || '.photo-wall',
            reflection: options.reflection || '.photo-wall-reflection',
            personImg: options.personImg || '#person-img',
        };

        this.dom = {
            scene: document.querySelector(this.selectors.scene),
            world: document.querySelector(this.selectors.world),
            wall: document.querySelector(this.selectors.wall),
            reflection: document.querySelector(this.selectors.reflection),
            personImg: document.querySelector(this.selectors.personImg),
        };

        //参数配置 (合并用户配置与默认值)
        this.config = Object.assign({
            //图片资源配置
            imageSource: [],
            personImage: null,
            allowImageRepeat: true,

            //墙体几何形状
            rows: 7,
            screensPerRow: 17, // 建议使用奇数，视觉上更对称
            screenWidth: 300,
            screenHeight: 170,
            gap: 10,
            radius: 'auto',
            spreadAngle: 240,

            //场景与动画
            worldTilt: -8,
            animationSpeed: 120,
            swayAngle: 40,

            //人物位置
            personZ: 'auto',
        }, options);

        this.imageList = [];
        this.animationStyleSheet = null;

        this.init();
    }

    /**
     * 初始化/重置整个场景
     */
    init() {
        this.processImageSource();
        this.updateWorldTransform();
        this.createOrUpdateAnimation();
        this.updatePerson();
        this.buildWall();
    }

    /**
     * 将传入的 imageSource 配置转换为统一的内部图片路径数组
     */
    processImageSource() {
        const {
            imageSource
        } = this.config;
        this.imageList = [];

        if (Array.isArray(imageSource)) {
            this.imageList = imageSource;
        } else if (typeof imageSource === 'object' && imageSource !== null && imageSource.basePath && Array.isArray(imageSource.files)) {
            this.imageList = imageSource.files.map(file => `${imageSource.basePath}${file}`);
        }

        if (this.imageList.length === 0) {
            console.warn("ArcWall: 图片源(imageSource)为空或格式不正确。");
        }
    }

    /**
     *如果radius为'auto'，则计算完美半径
     * @returns {number} - 最终用于变换的半径值 (始终为负)
     */
    _getCalculatedRadius() {
        if (this.config.radius !== 'auto') {
            return this.config.radius;
        }

        const {
            screenWidth,
            screensPerRow,
            spreadAngle
        } = this.config;
        // 计算每个屏幕之间的夹角
        const angleIncrement = spreadAngle / (screensPerRow > 1 ? screensPerRow - 1 : 1);

        // 使用三角函数(tan)计算能让屏幕边缘接触的精确半径
        // 公式: R = (W/2) / tan(angle/2)
        const angleInRad = (angleIncrement / 2) * (Math.PI / 180);
        const calculatedRadius = (screenWidth / 2) / Math.tan(angleInRad);

        // 返回负值，因为墙体在深处。乘以0.99是为了轻微补偿，确保绝对没有缝隙。
        return -(calculatedRadius * 0.99);
    }


    /**
     * 根据当前配置构建或重建照片墙
     */
    buildWall() {
        this.dom.wall.innerHTML = '';
        this.dom.reflection.innerHTML = '';
        if (this.imageList.length === 0) return;

        const wallElements = this.createWallElements();
        this.dom.wall.appendChild(wallElements);
        this.dom.reflection.appendChild(wallElements.cloneNode(true));
    }

    /**
     * 创建构成墙体的所有屏幕DOM元素
     * @returns {DocumentFragment}
     */
    createWallElements() {
        const fragment = document.createDocumentFragment();
        const {
            rows,
            screensPerRow,
            screenWidth,
            screenHeight,
            gap,
            spreadAngle,
            allowImageRepeat
        } = this.config;
        const totalImages = this.imageList.length;
        const effectiveRadius = this._getCalculatedRadius(); // 获取最终半径

        const angleIncrement = spreadAngle / (screensPerRow > 1 ? screensPerRow - 1 : 1);
        const startAngle = -spreadAngle / 2;

        let usedImageIndices = new Set();

        for (let i = 0; i < rows; i++) {
            const yPos = (i - (rows - 1) / 2) * (screenHeight + gap);

            for (let j = 0; j < screensPerRow; j++) {
                const screen = document.createElement('div');
                screen.className = 'screen';
                screen.style.width = `${screenWidth}px`;
                screen.style.height = `${screenHeight}px`;
                screen.style.marginLeft = `${-screenWidth / 2}px`;
                screen.style.marginTop = `${-screenHeight / 2}px`;

                const img = document.createElement('img');
                let imageIndex;

                if (allowImageRepeat) {
                    imageIndex = (i * screensPerRow + j) % totalImages;
                } else {
                    if (usedImageIndices.size >= totalImages) usedImageIndices.clear();
                    do {
                        imageIndex = Math.floor(Math.random() * totalImages);
                    } while (usedImageIndices.has(imageIndex));
                    usedImageIndices.add(imageIndex);
                }

                img.src = this.imageList[imageIndex];
                screen.appendChild(img);

                const angle = startAngle + j * angleIncrement;

                // 使用计算出的半径进行变换
                screen.style.transform = `rotateY(${angle}deg) translateZ(${effectiveRadius}px) translateY(${yPos}px)`;
                fragment.appendChild(screen);
            }
        }
        return fragment;
    }

    /**
     * 更新整个3D世界容器的倾斜度
     */
    updateWorldTransform() {
        this.dom.world.style.transform = `translateY(10%) rotateX(${this.config.worldTilt}deg)`;
    }

    /**
     * 更新中心人物的图片和位置
     */
    updatePerson() {
        let personImageSrc = this.config.personImage;
        if (!personImageSrc && this.imageList.length > 0) {
            personImageSrc = this.imageList[Math.floor(Math.random() * this.imageList.length)];
        }
        this.dom.personImg.src = personImageSrc || '';

        let personZ = this.config.personZ;
        if (personZ === 'auto') {
            personZ = this.calculateOptimalPersonZ();
        }
        this.dom.personImg.parentElement.style.transform = `translateX(-50%) translateZ(${personZ}px)`;
    }

    /**
     * 智能计算函数：根据墙体参数计算一个最佳的人物Z轴位置
     * @returns {number}
     */
    calculateOptimalPersonZ() {
        const effectiveRadius = this._getCalculatedRadius();
        const angleInRad = (this.config.spreadAngle / 2) * (Math.PI / 180);
        const zDepthOfWallEdge = Math.abs(effectiveRadius) * Math.cos(angleInRad);
        return -zDepthOfWallEdge + 300;
    }

    /**
     * 创建或更新CSS @keyframes 动画规则
     */
    createOrUpdateAnimation() {
        const {
            animationSpeed,
            swayAngle
        } = this.config;
        const animationName = 'arcWallSway';
        const keyframes = `@keyframes ${animationName} { from { transform: rotateY(${swayAngle}deg); } to { transform: rotateY(${-swayAngle}deg); } }`;

        if (!this.animationStyleSheet) {
            const style = document.createElement('style');
            document.head.appendChild(style);
            this.animationStyleSheet = style.sheet;
        }

        if (this.animationStyleSheet.cssRules.length > 0) {
            this.animationStyleSheet.deleteRule(0);
        }

        this.animationStyleSheet.insertRule(keyframes, 0);

        const animationValue = `${animationName} ${animationSpeed}s ease-in-out infinite alternate`;
        this.dom.wall.style.animation = animationValue;
        this.dom.reflection.style.animation = animationValue;
    }

    /**
     * 公共API：用于在实例化后动态更新配置参数
     * @param {object} newOptions
     */
    update(newOptions) {
        Object.assign(this.config, newOptions);

        if (newOptions.imageSource) this.processImageSource();
        if (newOptions.worldTilt !== undefined) this.updateWorldTransform();
        if (newOptions.animationSpeed !== undefined || newOptions.swayAngle !== undefined) this.createOrUpdateAnimation();
        if (newOptions.personZ !== undefined || newOptions.personImage !== undefined) this.updatePerson();

        const geometryChanged = [
            'rows', 'screensPerRow', 'screenWidth', 'screenHeight', 'gap',
            'radius', 'spreadAngle', 'allowImageRepeat', 'imageSource'
        ].some(key => newOptions[key] !== undefined);

        if (geometryChanged) this.buildWall();
    }
}


//示例
document.addEventListener('DOMContentLoaded', () => {

    const localImages = {
        basePath: '../../public/img/',
        files: Array.from({
            length: 15
        }, (_, i) => `${i + 1}.jpg`)
    };

    // 实例化ArcWall，大部分参数使用默认值，特别是radius: 'auto'
    const myWall = new ArcWall({
        imageSource: localImages,
        personImage: '../../public/img/1.jpg', // 指定人物
        rows: 8,
        animationSpeed: 100,
    });

    window.myWall = myWall;
});